import { NestFactory } from '@nestjs/core'
import { ValidationPipe, Logger } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'
import { NestExpressApplication } from '@nestjs/platform-express'
import { join } from 'path'
import compression from 'compression'
import helmet from 'helmet'
import cookieParser from 'cookie-parser'
import session from 'express-session'
import connectRedis from 'connect-redis'
import { createClient } from 'redis'
import { AppModule } from './app.module'
import { HttpExceptionFilter } from './common/filters/http-exception.filter'
import { ResponseTransformInterceptor } from './common/interceptors/response.interceptor'
import { LoggingInterceptor } from './common/interceptors/logging.interceptor'
import { LoggerService } from './logger/logger.service'

/**
 * 应用程序启动函数
 */
async function bootstrap() {
  const logger = new Logger('Bootstrap')

  try {
    // 创建NestJS应用实例
    const app = await NestFactory.create<NestExpressApplication>(AppModule, {
      logger: ['error', 'warn', 'log', 'debug', 'verbose'],
      cors: true
    })

    // 获取配置服务
    const configService = app.get(ConfigService)
    const port = configService.get<number>('PORT', 3000)
    const nodeEnv = configService.get<string>('NODE_ENV', 'development')

    // 设置全局前缀
    app.setGlobalPrefix('api', {
      exclude: ['/', '/health', '/ping', '/docs', '/docs-json']
    })

    // 信任代理（用于获取真实IP）
    app.set('trust proxy', 1)

    // 设置视图引擎和静态文件
    app.useStaticAssets(join(__dirname, '..', 'public'), {
      prefix: '/public/'
    })
    app.setBaseViewsDir(join(__dirname, '..', 'views'))
    app.setViewEngine('hbs')

    // 安全中间件
    app.use(
      helmet({
        contentSecurityPolicy: {
          directives: {
            defaultSrc: ["'self'"],
            styleSrc: ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
            fontSrc: ["'self'", 'https://fonts.gstatic.com'],
            imgSrc: ["'self'", 'data:', 'https:'],
            scriptSrc: ["'self'"]
          }
        },
        crossOriginEmbedderPolicy: false
      })
    )

    // 压缩中间件
    app.use(
      compression({
        filter: (req, res) => {
          if (req.headers['x-no-compression']) {
            return false
          }
          return compression.filter(req, res)
        },
        threshold: 1024 // 只压缩大于1KB的响应
      })
    )

    // Cookie解析器
    app.use(cookieParser(configService.get<string>('COOKIE_SECRET', 'your-secret-key')))

    // Session配置
    if (nodeEnv === 'production') {
      // 生产环境使用Redis存储session
      const RedisStore = connectRedis(session)
      const redisClient = createClient({
        socket: {
          host: configService.get<string>('redis.host'),
          port: configService.get<number>('redis.port')
        },
        password: configService.get<string>('redis.password'),
        database: configService.get<number>('redis.db', 0) + 3 // 使用不同的数据库
      })

      // 连接Redis客户端
      await redisClient.connect()

      app.use(
        session({
          store: new RedisStore({
            client: redisClient as any // 临时类型断言解决兼容性问题
          }),
          secret: configService.get<string>('SESSION_SECRET', 'your-session-secret'),
          resave: false,
          saveUninitialized: false,
          rolling: true,
          cookie: {
            maxAge: 24 * 60 * 60 * 1000, // 24小时
            httpOnly: true,
            secure: true, // HTTPS环境
            sameSite: 'strict'
          }
        })
      )
    } else {
      // 开发环境使用内存存储
      app.use(
        session({
          secret: configService.get<string>('SESSION_SECRET', 'dev-session-secret'),
          resave: false,
          saveUninitialized: false,
          rolling: true,
          cookie: {
            maxAge: 24 * 60 * 60 * 1000, // 24小时
            httpOnly: true,
            secure: false, // HTTP环境
            sameSite: 'lax'
          }
        })
      )
    }

    // 全局验证管道
    app.useGlobalPipes(
      new ValidationPipe({
        transform: true,
        transformOptions: {
          enableImplicitConversion: true
        },
        whitelist: true,
        forbidNonWhitelisted: true,
        disableErrorMessages: nodeEnv === 'production',
        validationError: {
          target: false,
          value: false
        }
      })
    )

    // 全局异常过滤器
    app.useGlobalFilters(new HttpExceptionFilter())

    // 全局拦截器
    const loggerService = app.get(LoggerService)
    const reflector = app.get('Reflector')
    app.useGlobalInterceptors(new ResponseTransformInterceptor(loggerService, reflector), new LoggingInterceptor())

    // Swagger API文档配置
    if (nodeEnv !== 'production') {
      const config = new DocumentBuilder()
        .setTitle('CMS API Documentation')
        .setDescription('内容管理系统 API 接口文档')
        .setVersion('1.0.0')
        .addBearerAuth(
          {
            type: 'http',
            scheme: 'bearer',
            bearerFormat: 'JWT',
            name: 'JWT',
            description: 'Enter JWT token',
            in: 'header'
          },
          'JWT-auth'
        )
        .addApiKey(
          {
            type: 'apiKey',
            name: 'X-API-Key',
            in: 'header',
            description: 'API Key for external access'
          },
          'API-Key'
        )
        .addServer(`http://localhost:${port}`, '开发环境')
        .addServer('https://api.yourdomain.com', '生产环境')
        .addTag('认证管理', '用户认证相关接口')
        .addTag('用户管理', '用户管理相关接口')
        .addTag('内容管理', '内容管理相关接口')
        .addTag('分类管理', '分类管理相关接口')
        .addTag('文件管理', '文件管理相关接口')
        .addTag('系统管理', '系统管理相关接口')
        .build()

      const document = SwaggerModule.createDocument(app, config, {
        operationIdFactory: (controllerKey: string, methodKey: string) => methodKey
      })

      SwaggerModule.setup('docs', app, document, {
        swaggerOptions: {
          persistAuthorization: true,
          displayRequestDuration: true,
          docExpansion: 'none',
          filter: true,
          showRequestHeaders: true,
          tryItOutEnabled: true
        },
        customSiteTitle: 'CMS API Documentation',
        customfavIcon: '/public/favicon.ico',
        customCss: `
          .swagger-ui .topbar { display: none }
          .swagger-ui .info { margin: 20px 0 }
          .swagger-ui .scheme-container { margin: 20px 0 }
        `
      })

      logger.log(`📚 API Documentation available at: http://localhost:${port}/docs`)
    }

    // 优雅关闭处理
    const gracefulShutdown = (signal: string) => {
      logger.log(`🔄 Received ${signal}, starting graceful shutdown...`)

      app
        .close()
        .then(() => {
          logger.log('✅ Application closed successfully')
          process.exit(0)
        })
        .catch(error => {
          logger.error('❌ Error during application shutdown:', error)
          process.exit(1)
        })
    }

    // 监听关闭信号
    process.on('SIGTERM', () => gracefulShutdown('SIGTERM'))
    process.on('SIGINT', () => gracefulShutdown('SIGINT'))

    // 未捕获异常处理
    process.on('uncaughtException', error => {
      logger.error('❌ Uncaught Exception:', error)
      process.exit(1)
    })

    process.on('unhandledRejection', (reason, promise) => {
      logger.error('❌ Unhandled Rejection at:', promise, 'reason:', reason)
      process.exit(1)
    })

    // 启动应用
    await app.listen(port, '0.0.0.0')

    // 启动成功日志
    logger.log(`🚀 Application is running on: http://localhost:${port}`)
    logger.log(`🌍 Environment: ${nodeEnv}`)
    logger.log(`📊 Health check: http://localhost:${port}/health`)

    if (nodeEnv !== 'production') {
      logger.log(`📖 API Docs: http://localhost:${port}/docs`)
    }

    // 显示应用信息
    const packageJson = require('../package.json')
    logger.log(`📦 Application: ${packageJson.name} v${packageJson.version}`)
    logger.log(`🔧 Node.js: ${process.version}`)
    logger.log(`💾 Memory usage: ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)} MB`)
  } catch (error) {
    logger.error('❌ Failed to start application:', error)
    process.exit(1)
  }
}

// 启动应用
bootstrap()
